home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Tech Arsenal 1
/
Tech Arsenal (Arsenal Computer).ISO
/
tek-04
/
ddj1291.zip
/
STAT.ZIP
/
SOURCE.ZIP
/
PATICK.ASM
< prev
next >
Wrap
Assembly Source File
|
1990-05-09
|
6KB
|
238 lines
TITLE patick - IBM PC / Clone Clock Tick CS:IP Grabber
;
; File: patick.asm
;
; Copyright 1990
; Fred Motteler and Applied Microsystems Corporation
; All Rights Reserved
;
; Description:
;
; This file contains three functions:
;
; C callable:
;
; void painit(bufferLP, lengthN) Initialize grabber interrupt vector
; int paclose() Close grabber interrupt vector
;
; Interrupt routine, this is treated like part of painit():
;
; patick Grab CS:IP value
;
; These functions are configured for small model.
;
; Stack frame structure for painit():
;
stkfr STRUC
OLD_FR DW ? ; Previous stack frame pointer
RETADDR DW ? ; Return address to caller
BUFFERP DW ? ; Pointer to buffer to use
BUFLEN DW ? ; Length of buffer (in longwords)
stkfr ENDS
;
; Stack frame structure for clock tick timer routine.
;
intfr STRUC
INT_FR DW ? ; Pre-interrupt stack frame pointer
IP_VAL DW ? ; Pre-interrupt IP value
CS_VAL DW ? ; Pre-interrupt CS value
intfr ENDS
TIMER EQU 8h ; Timer interrupt vector number
DGROUP GROUP _DATA
_DATA SEGMENT WORD PUBLIC 'DATA'
ASSUME DS:DGROUP
bufptr DW 0 ; Starting point of buffer
bufsiz DW 0 ; Number of longwords in the buffer
bufindx DW 0 ; Next location of buffer to use
bufwrap DB 0 ; Flag if buffer has wrapped...
_DATA ENDS
_TEXT SEGMENT BYTE PUBLIC 'CODE'
ASSUME CS:_TEXT
;
; void paopen (unsigned long *bufferLP, int lengthN)
;
; This a C callable function to initialize the CS:IP grabber and
; start it up. bufferLP points the buffer of where to write CS:IP
; values. lengthN is the length of the buffer in longwords.
;
PUBLIC paopen
paopen PROC NEAR
push bp
mov bp,sp
push si
push di
push es
;
; Set up the local buffer pointer values from those passed on the
; stack.
;
mov ax,[bp].BUFFERP ; Get pointer to start of buffer
mov bufptr,ax
mov ax,[bp].BUFLEN ; Get length of the buffer
shl ax,1 ; convert longword length to byte length
shl ax,1
mov bufsiz,ax
xor ax,ax ; Start at the beginning of the buffer
mov bufindx,ax
mov bufwrap,al ; Reset buffer wrap flag
;
; Save the original clock tick interrupt vector.
;
mov al,TIMER ; interrupt number into al
mov ah,35h ; DOS function = get vector
int 21h ; DOS returns old vector in es:bx
mov cs:oldseg,es ; save old segment
mov cs:oldoff,bx ; save old offset
;
; Disable interrupts while changing the interrupt vector.
;
cli
;
; Change the clock tick interrupt routine to point at local interrupt
; routine.
;
mov al,TIMER ; vector number
mov ah,25h ; DOS function = set vector
mov dx,OFFSET patick ; point to our interrupt handler
push ds ; don't lose ds, we need to get to local data
push cs ; move this cs to ds
pop ds ;
int 21h ; set the new vector
pop ds ; restore ds
;
; Enable interrupts and return;
;
pop es
pop di
pop si
pop bp
sti
ret
;
; Clock tick grabber routine
;
; This routine samples the CS:IP that were pushed on to the stack
; when the interrupt occurs.
;
patick: push bp
mov bp,sp ; Treat CS:IP values like stack frame
push ax
push bx
push ds
;
; Get the local ds to allow access to local variables.
;
mov ax,DGROUP
mov ds,ax
;
; Use bx as a pointer to the recording buffer
;
mov bx,bufptr
add bx,bufindx
;
; Grab the pre-interrupt CS:IP values off the stack
;
mov ax,[bp].IP_VAL ; grab the IP
mov [bx],ax ; save the IP in the recording buffer
inc bx
inc bx
mov ax,[bp].CS_VAL ; grab the CS
mov [bx],ax ; save the CS in the recording buffer
inc bx
inc bx
;
; Check if we are at the end of the buffer
;
sub bx,bufptr ; get the byte offset index back again
mov ax,bufsiz ; get the buffer byte length
cmp ax,bx
jne notend ; jump if not at the end of the buffer
;
; At the end of the buffer
;
mov bx,0 ; reset the buffer index
mov al,0ffh ; set flag to indicate buffer wrap
mov bufwrap,al
;
; Write out modified buffer index
;
notend: mov bufindx,bx
;
; Clean up
;
pop ds
pop bx
pop ax
pop bp
;
; Jump to the original interrupt service routine. An immediate jump
; is used so no segment registers are required.
;
DB 0eah ; jmp immediate, to the offset:segment
; selected below (brute force approach).
;
; Original interrupt handler's offset and segment values. These are
; in the current code segment to allow the interrupt routine given
; here to directly jump to the original interrupt routine.
;
oldoff DW 0 ; Room for original timer interrupt offset
oldseg DW 0 ; Room for original timer interrupt segment
paopen ENDP
;
; int paclose()
;
; This is a C callable function to close the CS:IP grabber and
; return the number of CS:IP values grabbed.
;
PUBLIC paclose
paclose PROC NEAR
push bp
mov bp,sp
push si
push di
push es
;
; Disable interrupts while the original interrupt vector is restored.
;
cli
mov al,TIMER ; get interrupt number
mov ah,25h ; DOS function = set vector
push ds ;
mov dx,cs:oldoff ; old timer offset
mov ds,cs:oldseg ; old timer segment
int 21h ; restore old vector
pop ds ;
;
; Enable interrupts.
;
sti
;
; Calculate the number of CS:IP values
;
cmp bufwrap,0 ; check if the buffer has wrapped
jne wrapped ; jump if it has wrapped
mov ax,bufindx ; no wrap, return buffer index as count
jmp done
wrapped: mov ax,bufsiz ; wrapped, return buffer size as count
;
; Clean up stack and return
;
done: shr ax,1 ; Return count in number of CS:IP pairs
shr ax,1
pop es
pop di
pop si
pop bp
ret
paclose ENDP
_TEXT ENDS
END